package edu.cicese.alz.reports;

import edu.cicese.alz.Query;
import edu.cicese.alz.TimeUtil;
import edu.cicese.alz.util.IncenseUtil;

import java.awt.Color;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TreeSet;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 6/08/12
 * Time: 12:41 PM
 */
public class NFCReport extends Report{

	protected List<NFCTag> nfcTags;
	private Color colorNoData;
//	private long offset = 0;
	private long offset = 3600000;

	private List<NFCMeasure> dayTags = new ArrayList<>();
//	private Map<String, Integer[]> tags = new HashMap<>();
//	private String[][] userTags;
	private int day = 0;

	public NFCReport(TreeSet<Integer> userIDs, Date beginDate, Date endDate, Date dayBeginDate, Date dayEndDate,
	                 boolean showCharts, boolean saveCharts, List<NFCTag> profileTags, Color colorNoData) {

		super(userIDs, beginDate, endDate, dayBeginDate, dayEndDate, showCharts, saveCharts);

		this.nfcTags = getSelectedTags(profileTags);
		this.colorNoData = colorNoData;
	}

	// Constructor for the Combined Report
	public NFCReport(long tsBegin, long tsEnd, int beginHour, int beginMinute, int beginSecond, int endHour,
	                 int endMinute, int endSecond, int days, int periods, List<NFCTag> profileTags) {

		super(tsBegin, tsEnd, beginHour, beginMinute, beginSecond, endHour, endMinute, endSecond, days, periods);

		this.nfcTags = getSelectedTags(profileTags);
	}


	public void createCharts() {
		String outputDir = "";
		if (saveCharts) {
			outputDir = IncenseUtil.getReportChartsDir("nfc");
		}

		for (int userID : userIDs) {
			plot(userID, getValues(userID), outputDir);
		}
	}


	public double[][] getValues(int userID) {
		ResultSet resultSet = Query.executeQuery(Query.queryNFCData(userID, tsBegin, tsEnd));
		List<NFCMeasure> nfcMeasures = new ArrayList<>();
		try {
			while (resultSet.next()) {
				nfcMeasures.add(new NFCMeasure(resultSet.getString(1), resultSet.getLong(2)));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}

		double[][] values = new double[3][periods * days];

		Calendar cal = TimeUtil.getDayTimestamp(tsBegin);
		long dayTimestamp = cal.getTimeInMillis() + offset;
		long tsAux = dayTimestamp + startTime;

//		userTags = new String[20][days];

		if (!nfcMeasures.isEmpty()) {
			for (int day = 0; day < days; day++) {
				for (int p = 0; p < periods; p++) {
					values[0][(day * periods + p)] = dayTimestamp;
					values[1][(day * periods + p)] = p * PERIOD_LENGTH + startTime;
					values[2][(day * periods + p)] = getValue(nfcMeasures, tsAux);

					tsAux += PERIOD_LENGTH;
				}

				cal.add(Calendar.DAY_OF_MONTH, 1);
				dayTimestamp = cal.getTimeInMillis() + offset;
				tsAux = dayTimestamp + startTime;

				// Report
				for (int i = 0; i < nfcTags.size(); i++) {
//					List<String> matches = new ArrayList<>();
					for (NFCMeasure nfcMeasure : dayTags) {
						if (nfcMeasure.getMessage().equals(nfcTags.get(i).getProfileCheckBox().getText())) {
//							matches.add(TimeUtil.getStringDateFromMs(nfcMeasure.getTimestamp() - offset, TimeUtil.timeFormat));
							System.out.println(
											userID + " " +
											(i + 1) + " " +
											TimeUtil.getStringDateFromMs(nfcMeasure.getTimestamp() - offset, TimeUtil.usaFormat) + " " +
											TimeUtil.getStringDateFromMs(nfcMeasure.getTimestamp() - offset, TimeUtil.noSecondsFormat)
							);
						}
					}

//					userTags[i][day] = matches.toString();
				}

//				for (NFCMeasure nfcMeasure : dayTags) {
//					List<String> matches = new ArrayList<>();
//					for (int i = 0; i < nfcTags.size(); i++) {
//						if (nfcMeasure.getMessage().equals(nfcTags.get(i).getProfileCheckBox().getText())) {
//							matches.add(nfcMeasure)
//						}
//					}
//					userTags[i][day]++;
//				}
				dayTags.clear();
				// Report
			}
		}

		else {
			for (int day = 0; day < days; day++) {
				for (int p = 0; p < periods; p++) {
					values[0][(day * periods + p)] = dayTimestamp;
					values[1][(day * periods + p)] = p * PERIOD_LENGTH + startTime;
					values[2][(day * periods + p)] = 0.5;
				}
				cal.add(Calendar.DAY_OF_MONTH, 1);
				dayTimestamp = cal.getTimeInMillis() + offset;
			}
		}

//		System.out.println("User: " + userID);
//		for (int d = 0; d < days; d++) {
//			for (int i = 0; i < 20; i++) {
//				System.out.print(userTags[i][d] + " ");
//			}
//			System.out.println();
//		}

		return values;
	}

	private double getValue(List<NFCMeasure> nfcMeasures, long tsAux) {
		long tsA = tsAux;
		long tsB = tsAux + PERIOD_LENGTH;

		double value = 0.5;
		boolean found = false;

		while (!nfcMeasures.isEmpty()) {
			long ts = nfcMeasures.get(0).getTimestamp();

			if (ts > tsB) {
				break;
			}

			if (ts > tsA && ts <= tsB) {
				if (!found) {
					for (int i = 0; i < nfcTags.size(); i++) {
						if (nfcMeasures.get(0).getMessage().equals(nfcTags.get(i).getProfileCheckBox().getText())) {
							value = i + 1.5;
							found = true;
						}
					}
				}
			}

			dayTags.add(nfcMeasures.get(0));
			nfcMeasures.remove(0);
		}

		return value;
	}


	private void plot(int userID, double[][] values, String outputDir) {
		FrameNFCBlock frameNFCBlock = new FrameNFCBlock(userID, startTime, nfcTags, colorNoData);
		frameNFCBlock.plotData(values, days);

		if (saveCharts) {
			frameNFCBlock.setOutputDir(outputDir);
		}

		if (showCharts) {
			frameNFCBlock.pack();
			frameNFCBlock.setVisible(true);
		}
		else {
			frameNFCBlock.dispose();
		}
	}


	private List<NFCTag> getSelectedTags(List<NFCTag> profileTags) {
		List<NFCTag> nfcTags = new ArrayList<>();
		for(NFCTag nfcTag : profileTags) {
			if (nfcTag.getProfileCheckBox().isSelected()) {
				nfcTags.add(nfcTag);
			}
		}

		return nfcTags;
	}
}
